# stackdisplay.py                               David MacQuigg  ece373  11/10/07
'''Module to maintain and display a list of operands for a Multi-Hetero-Generic
Calculator.  This module does not perform any operations on the data, but does
include all the "circuitry" to store and retrieve the operands, move them around
in the stack, and display an appropriate string representation of each
operand.'''

from graphics import *  # primitives for the GUI (from John Zelle's excellent
                        # package http://mcsp.wartburg.edu/zelle/python/).
from button import Button

class StackDisplay(GraphWin):
    '''Store and retrieve, move and display operands in a Calculator stack.'''

    def __init__(self, width, regList):
        '''Set up a stack display with given width (number of chars) and given
        height (number of items in regList).  A StackDisplay does not check the
        validity of operands. It just uses whatever __str__ method is provided
        by each operand to generate a string and display it in the appropriate
        register.  The operands themselves are maintained as the original
        objects provided by the operations module.'''
        
        self.width = width
        self.regList = regList
        numRegs = len(regList)
        w = width * 10    # 10 pixels per character
        h = numRegs * 30  # 30 pixels per row
        GraphWin.__init__(self, 'stack', w, h)
        self.setCoords(0,0,width, numRegs+2)  # leave for buttons at top
        row = 0
        for reg in regList:
            row += 1
            e = Entry(Point(width/2, row), width)  # An Entry widget will allow
                               # direct editing of the register contents.
            e.setText(reg)
            e.draw(self)
        b = Button(self, Point(width/2, numRegs+1), 1.75, .75, "Refresh")
        b.activate()

    def displayLine(self, regnum, strValue):
        '''Refresh the display of register regnum, replacing its current 
        contents with strValue.  Throw IndexError if regnum is out of
        range, and TypeError if strValue is not a string.'''
    
    def refresh(self):
        '''Refresh the display using the existing regList.  Lists are mutable,
           and StackDisplays keep only a shallow copy.  The number of items
           should not change, however.  Throw an exception if that happens.'''

    def enter(self, operand):
        '''Push a new operand onto the bottom of the stack, discarding the top
        operand, if necessary.'''

    def pop2(self):
        '''return a pair of operands from the bottom two registers.  Leave all
        registers as is.'''

    def store(self, result):
        '''Store the result of an operation in the bottom register, moving the
        stack down, leaving the top register empty.'''

    def exchange(self):
        '''Exchange the bottom two operands.'''
     
    def rollUp(self):
        '''Roll the stack up, moving the top operand to the bottom.'''

    def rollDown(self):
        '''Roll the stack down, moving the bottom operand to the top.'''

    def pushUp(self):
        '''Move the stack up, leaving a copy of the bottom operand in place.'''

    def setStack(self, index, value):
        self.regList[index]=value
        row = 0
        for reg in self.regList:
            row += 1
            e = Entry(Point(self.width/2, row), self.width)  # An Entry widget will allow
                               # direct editing of the register contents.
            e.setText(reg)
            e.draw(self)


if __name__ == '__main__':
    ''' Run some tests'''
    
    # Sample data.  Various structures that might be useful for representing
    # polynomials, matrices, etc.
    dict1 = {1:10, 3:30}             # A polynomial
    list1 = [[4,5,6,7],[8,9,10,11]]  # A matrix
    regList = [1,2.1,3+2j,dict1,list1]    # 5 items here
    
    stackwin = StackDisplay(30, regList)
    
##    stackwin.close()
    

##    e = Entry(Point(2,3), 5)
##    e.setText('0.0')
##    e.draw(stackwin)

##    stackwin.getMouse()  # listen up, you stackwin!
##    t = e.getText()
##    print t
##    stackwin.getMouse()
##    stackwin.close()
